import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * In Eclipse, the JUnit 3 test runner is required in order to not execute this class.  Otherwise you will get an
 * {@code no runnable methods} exception.
 * 
 * @author brianegge
 * @license http://www.freebsd.org/copyright/license.html  BSD License (4 Clause)
 */
public final class AllTestSuite {
	
    public static Test suite() {
        TestSuite suite = new TestSuite();
        File testDir = new File("test");
        try {
            assert testDir.isDirectory();
            addTestCase(testDir, suite);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return suite;
    }

    /**
    * Recursively add all tests
    * We use {@code Class#forName(String)} so we have to do some unchecked casting 
    */
    @SuppressWarnings("unchecked")
	private static void addTestCase(File f, TestSuite suite) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //If this is a directory, walk each file/dir in that directory
        if (f.isDirectory()) {
            if (f.getName().equals(".svn")) {
                return;
            }
            File[] list = f.listFiles();
            for (File file : list) {
                addTestCase(file, suite);
            }
        } else if (f.getName().endsWith("UnitTest.java")) {
            Pattern pattern = Pattern.compile("test[/\\\\](.*)\\.java");
            Matcher match = pattern.matcher(f.getPath());
            boolean found = match.find();
            assert found : "Couldn't find " + pattern + " in " + f.getPath();
            String name = match.group(1).replaceAll("[/\\\\]", ".");
            Class<? extends TestCase> clazz = (Class<? extends TestCase>) Class.forName(name);
            suite.addTest(new TestSuite(clazz));
        }
    }

}
